<template>

    <div class="showDicom">
        <div class="showDicom_left">
            <h6 class="card-header">患者信息</h6>
            <div class="showDicom_msg">

                <el-card  shadow="never" style="background-color: transparent;border:0px;">
                
                    <p class="text">{{'id:' + person.id}}    </p>
                    <p class="text">{{'姓名:' + person.name}}</p>
                	<p class="text">{{'性别:' + person.sex}} </p>
                	<p class="text">{{'年龄：' + person.age}}</p>
                	<p class="text">{{'电话:' + person.tel}} </p>
                	<p class="text">{{'部位:' + person.zone}}</p>
                	<p class="text">{{'过敏史:' + person.his}}</p>
                			
                  </el-card>
            </div>
            <h6 class="card-header">操作步骤</h6>
            <div class="showDicom_steps">
                <div style="height: 210px; max-width: 600px;margin-top: 10px;">
                    <el-steps direction="vertical" :active="-1">
                        <el-step title="Step 1 上传DICOM文件" />
                        <el-step title="Step 2 使用工具注释" />
                        <el-step title="Step 3 保存图片" />
                    </el-steps>
                </div>
            </div>
        </div>

        <div class="showDicom_middle">

            <div class="showDicom_middle_upload">
                <!-- <button :hidden="!loaeded" @click="toggleLengthTool">Length Tool</button> -->
                <!-- <button :hidden="!loaeded" @click="colorChange">滤镜</button> -->
                <div class="cornerstone_content">
                    <div ref="cornerstone-shade" class="cornerstone_shade" @change="handleFileChange" v-if="showShade">
                        <div class="cornerstone_dragger">
                            <input type="file" multiple id="selectFile" @change="handleFileChange"
                                class="cornerstone_dragger_input" />
                            <img src="../static/image/uploadfile.png" alt="上传DICOM文件" class="cornerstone_dragger_img" />
                            <p style="font-size: 1.2vw;margin-top: 30px;">Drop DICOM file here or click to upload</p>
                        </div>
                    </div>
                    <div class="cornerstone_title" v-show="!showShade">提示：左键灰度，滚轮切换栈视图，右键缩放</div>
                    <div ref="cornerstone-element" class="cornerstone_element" id="cornerstone-element"
                        :style="`filter: sepia() saturate(8) hue-rotate(${colorNum === 0 ? null : colorNum}deg)`">
                    </div>
                    <!-- <div v-if="dicomMessage">
                        <div v-for=" item, index  in  dicomMessage " :key="index"> {{ item.title }} : {{ item.val }}
                        </div>
                    </div> -->

                </div>
            </div>

        </div>

        <div class="showDicom_right">
            <div class="showDicom_right_title"> 工具栏 </div>
            <button class="showDicom_btn"
                :class="!showShade && leftTool == 'WindowLevelTool' ? 'showDicom_btn_active' : ''"
                @click="toggleWindowLevelTool">对比度变换</button>
            <button class="showDicom_btn" :class="!showShade && leftTool == 'LengthTool' ? 'showDicom_btn_active' : ''"
                @click="toggleLengthTool">长度注释</button>
            <!-- <button class="showDicom_btn" @click="colorChange">颜色滤镜</button> -->
            <div class="slider-demo-block">
                <span class="demonstration">
                    [绿] <- 渲染颜色 -> [红]
                </span>
                <el-slider v-model="colorNum" :step="80" :max="320" show-stops @input="colorChange" />
            </div>
            <button class="showDicom_btn" @click="resetAllTool">重置</button>
            <button class="showDicom_btn" @click="domToCanvas">保存</button>
        </div>

    </div>

</template>

<script>
import {
    RenderingEngine,
    Enums,
    metaData,
    eventTarget,
} from "@cornerstonejs/core";
import cornerstoneDICOMImageLoader from "@cornerstonejs/dicom-image-loader";
import * as cornerstoneTools from "@cornerstonejs/tools";
import { initCornerstone } from "../cornerstone/index";
import {
    convertMultiframeImageIds,
    prefetchMetadataInformation,
} from "../cornerstone/convertMultiframeImageIds";
import html2canvas from "html2canvas";
import { ElMessage, ElMessageBox } from 'element-plus'
import { h } from 'vue'

const {
    PanTool,
    WindowLevelTool,
    StackScrollMouseWheelTool,
    ZoomTool,
    LengthTool,
    ToolGroupManager,
    Enums: csToolsEnums,
} = cornerstoneTools;
const { ViewportType } = Enums;
const { MouseBindings } = csToolsEnums;
const toolGroupId = "myToolGroup";

export default {
    name: "ViewerComponent",
    data() {
        return {
            toolGroupId: "myToolGroup",
            viewport: null,
            element: null,
            toolGroup: null,
            loaeded: false,
            dicomMessage: [],
            typeExtenstions: ["dcm"],
            leftTool: 'WindowLevelTool',
            colorNum: 0,
            showShade: true,
			person:{
				id:"2024001",
				name:"李明",
				sex:"男",
				age:"20",
				tel:"188182823",
				zone:"肺部",
				his:"无"
			},
        };
    },
    async mounted() {
        // 禁用右键菜单
        const element = this.$refs["cornerstone-element"];
        element.oncontextmenu = (e) => e.preventDefault();

        // 拖拽上传
        this.element = element;
        const shadeRef = this.$refs["cornerstone-shade"]
        shadeRef.addEventListener("dragover", this.handleDragOver, false);
        shadeRef.addEventListener("drop", this.handleFileSelect, false);


        await this.run();
        // 工具监听
        this.eventHandlers();
    },
    unmounted() {
        // const shadeRef = this.$refs["cornerstone-shade"]
        // shadeRef.removeEventListener("dragover", this.handleDragOver, false);
        // shadeRef.removeEventListener("drop", this.handleFileSelect, false);
        cornerstoneTools.removeTool(PanTool);
        cornerstoneTools.removeTool(WindowLevelTool);
        cornerstoneTools.removeTool(StackScrollMouseWheelTool);
        cornerstoneTools.removeTool(ZoomTool);
        cornerstoneTools.removeTool(LengthTool);
        ToolGroupManager.destroy()
    },
    methods: {
        renderAnnotaions() {
            const annotation = localStorage.getItem("annotation");
            if (annotation) {
                cornerstoneTools.annotation.state.addAnnotation(
                    JSON.parse(annotation),
                    this.viewport.element
                );
            }
        },
        /** 工具操作监听 */
        eventHandlers() {
            eventTarget.addEventListener(
                cornerstoneTools.Enums.Events.ANNOTATION_ADDED,
                (csToolsEvent) => {
                    // console.log("ANNOTATION_ADDED");
                    const annotationAddedEventDetail = csToolsEvent.detail;
                    // console.log(annotationAddedEventDetail);
                }
            );

            eventTarget.addEventListener(
                cornerstoneTools.Enums.Events.ANNOTATION_COMPLETED,
                (csToolsEvent) => {
                    // console.log("ANNOTATION_COMPLETED");
                    const annotationAddedEventDetail = csToolsEvent.detail;
                    // console.log(annotationAddedEventDetail);
                    localStorage.setItem(
                        "annotation",
                        JSON.stringify(annotationAddedEventDetail.annotation)
                    );
                }
            );

            eventTarget.addEventListener(
                cornerstoneTools.Enums.Events.ANNOTATION_MODIFIED,
                (csToolsEvent) => {
                    // console.log("ANNOTATION_MODIFIED");
                    const annotationAddedEventDetail = csToolsEvent.detail;
                    // console.log(annotationAddedEventDetail);
                }
            );

            eventTarget.addEventListener(
                cornerstoneTools.Enums.Events.ANNOTATION_REMOVED,
                (csToolsEvent) => {
                    // console.log("ANNOTATION_REMOVED");
                    const annotationAddedEventDetail = csToolsEvent.detail;
                    // console.log(annotationAddedEventDetail);
                }
            );
        },

        /** 上传文件 解析DICOM */
        handleFileChange(e) {
            const fileList = e.target.files;
            this.dicomLoader(fileList);
        },

        /** 
         * 解析DICOM 返回imageId
         * @param {Array} fileList
         * return {Array} cache
         */
        dicomLoader(fileList) {
            let flag = true;
            const cache = [];
            for (let i = 0; i < fileList.length; i++) {
                const file = fileList[i];
                if (!this.checkFileType(file)) {
                    flag = false;
                    return
                }
                const imageId = cornerstoneDICOMImageLoader.wadouri.fileManager.add(file);
                cache[i] = imageId;
            }
            // const file = e.target.files[0];
            // const imageId = cornerstoneDICOMImageLoader.wadouri.fileManager.add(file);
            // console.log(cache);
            if (flag) {
                // 开启渲染 打开遮罩层
                this.loadAndViewImage(cache);
                this.showShade = false
            }
        },

        /** 切换长度工具 */
        toggleLengthTool() {

            if (!this.checkViewport()) return

            this.leftTool = 'LengthTool'
            this.toolGroup.setToolPassive(WindowLevelTool.toolName);

            this.toolGroup.setToolActive(LengthTool.toolName, {
                bindings: [
                    {
                        mouseButton: MouseBindings.Primary,
                    },
                ],
            });
        },
        /** 切换长度工具 */
        toggleWindowLevelTool() {

            if (!this.checkViewport()) return

            this.leftTool = 'WindowLevelTool'

            this.toolGroup.setToolPassive(LengthTool.toolName);

            this.toolGroup.setToolActive(WindowLevelTool.toolName, {
                bindings: [
                    {
                        mouseButton: MouseBindings.Primary, // Left Click
                    },
                ],
            });
        },
        /** 检查有无视图  */
        checkViewport() {
            if (this.showShade || this.viewport.viewportStatus === 'noData') {
                ElMessage({
                    type: 'warning',
                    message: '请先上传DICOM文件',
                })
                return false
            }
            return true
        },
        /** 检查上传的文件类型 */
        checkFileType(file) {
            const type = file.name.split('.').pop();
            if (!this.typeExtenstions.includes(type)) {
                ElMessage({
                    type: 'error',
                    message: '类型错误: 请上传DICOM文件',
                })
                return false
            }
            return true
        },
        async run() {

            // Init Cornerstone and related libraries
            await initCornerstone();

            console.log("工具组：", ToolGroupManager.getAllToolGroups())
            if (ToolGroupManager.getAllToolGroups().length === 0) {
                cornerstoneTools.addTool(PanTool);
                cornerstoneTools.addTool(WindowLevelTool);
                cornerstoneTools.addTool(StackScrollMouseWheelTool);
                cornerstoneTools.addTool(ZoomTool);
                cornerstoneTools.addTool(LengthTool);
            }

            /** 定义一个工具组，定义鼠标事件如何映射到使用该组的任何视图的工具命令（初始化滚动，缩放，灰度工具） */
            const toolGroup = ToolGroupManager.createToolGroup(toolGroupId);

            /** 向工具组中添加工具 */
            toolGroup.addTool(WindowLevelTool.toolName);
            toolGroup.addTool(PanTool.toolName);
            toolGroup.addTool(ZoomTool.toolName);
            toolGroup.addTool(StackScrollMouseWheelTool.toolName);
            toolGroup.addTool(LengthTool.toolName);

            /** 设置工具的初始状态，这里所有的工具都是活动的，并且绑定到不同的鼠标输入 */
            toolGroup.setToolPassive(LengthTool.toolName);
            toolGroup.setToolActive(WindowLevelTool.toolName, {
                bindings: [
                    {
                        mouseButton: MouseBindings.Primary, // Left Click
                    },
                ],
            });
            toolGroup.setToolActive(PanTool.toolName, {
                bindings: [
                    {
                        mouseButton: MouseBindings.Auxiliary, // Middle Click
                    },
                ],
            });
            toolGroup.setToolActive(ZoomTool.toolName, {
                bindings: [
                    {
                        mouseButton: MouseBindings.Secondary, // Right Click
                    },
                ],
            });

            /** 由于Stack Scroll鼠标滚轮是使用'mouseWheelCallback'钩子而不是鼠标按钮的工具，所以它不需要分配任何鼠标按钮。 */
            toolGroup.setToolActive(StackScrollMouseWheelTool.toolName);

            // Get Cornerstone imageIds and fetch metadata into RAM

            // Instantiate a rendering engine
            const renderingEngineId = "myRenderingEngine";
            const renderingEngine = new RenderingEngine(renderingEngineId);

            // Create a stack viewport
            const viewportId = "CT_STACK";
            const viewportInput = {
                viewportId,
                type: ViewportType.STACK,
                element: this.element,
                defaultOptions: {
                    background: [0.2, 0, 0.2],
                },
            };

            renderingEngine.enableElement(viewportInput);

            // Get the stack viewport that was created
            this.viewport = renderingEngine.getViewport(viewportId);

            toolGroup.addViewport(viewportId, renderingEngineId);
            this.toolGroup = toolGroup;

        },
        /** 拖拽上传 */
        handleFileSelect(evt) {
            // console.log(evt);
            evt.stopPropagation();
            evt.preventDefault();

            // Get the FileList object that contains the list of files that were dropped
            const files = evt.dataTransfer.files;

            // this UI is only built for a single file so just dump the first one
            // const file = files[0];
            // const imageId = cornerstoneDICOMImageLoader.wadouri.fileManager.add(file);
            // this.loadAndViewImage(imageId);
            this.dicomLoader(files)
        },
        /** 拖拽清除默认事件 */
        handleDragOver(evt) {
            evt.stopPropagation();
            evt.preventDefault();
            evt.dataTransfer.dropEffect = "copy"; // Explicitly show this is a copy.
        },
        /** 视图信息 */
        async loadAndViewImage(imageId) {
            await prefetchMetadataInformation([...imageId]);
            const stack = convertMultiframeImageIds([...imageId]);

            // try {
            //     this.viewport.setStack(stack)
            // } catch (error) {
            //     console.log("setStack");
            //     await this.run();
            //     // 工具监听
            //     this.eventHandlers();
            // }
            console.log("setStack", this.viewport);
            // Set the stack on the viewport
            this.viewport.setStack(stack).then(() => {
                // Set the VOI of the stack
                // viewport.setProperties({ voiRange: ctVoiRange });
                // Render the image
                this.viewport.render();

                // const imageData = this.viewport.getImageData();

                const {
                    pixelRepresentation,
                    bitsAllocated,
                    bitsStored,
                    highBit,
                    photometricInterpretation,
                } = metaData.get("imagePixelModule", imageId[0]);

                const voiLutModule = metaData.get("voiLutModule", imageId[0]);

                const sopCommonModule = metaData.get("sopCommonModule", imageId[0]);
                const transferSyntax = metaData.get("transferSyntax", imageId[0]);

                // console.log("sopCommonModule", sopCommonModule, transferSyntax, voiLutModule, pixelRepresentation, bitsAllocated, bitsStored, highBit, photometricInterpretation);


                // 添加DICOM信息
                this.dicomMessage.push({
                    title: 'sopClassUID',
                    val: sopCommonModule.sopClassUID,
                }, {
                    title: 'sopInstanceUID',
                    val: sopCommonModule.sopInstanceUID,
                }, {
                    title: 'transferSyntaxUID',
                    val: transferSyntax.transferSyntaxUID,
                }, {
                    title: '宽度',
                    val: voiLutModule.windowWidth[0]
                },
                    {
                        title: '高度',
                        val: voiLutModule.windowWidth[1]
                    }
                );



                this.loaeded = true;
                this.renderAnnotaions();
            });
        },
        /** 滤镜 */
        colorChange() {
            if (!this.checkViewport()) {
                this.colorNum = 0;
            }
        },
        /** 保存图片 */
        async saveCanvas() {
            // 获取目标元素的引用
            const targetElement = this.$refs["cornerstone-element"];

            try {
                // 使用html2canvas截取目标元素
                const canvas = await html2canvas(targetElement);

                // 将截图转换为DataURL
                const dataURL = canvas.toDataURL("image/png");

                // 创建一个虚拟链接并模拟点击下载
                const a = document.createElement("a");
                a.href = dataURL;
                a.download = `image-${Date.now()}.png`;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
            } catch (error) {
                console.error("图片保存错误:", error);
            }
        },
        /** 转换为图片 */
        async domToCanvas() {

            if (!this.checkViewport()) return

            // 获取目标元素的引用
            const targetElement = this.$refs["cornerstone-element"];

            try {
                // 使用html2canvas截取目标元素
                const canvas = await html2canvas(targetElement);

                // 将截图转换为DataURL
                const dataURL = canvas.toDataURL("image/png");

                // 预览确认是否下载
                ElMessageBox.confirm(
                    h('div', null, [
                        h('span', null, '是否下载此图片？'),
                        h('img', { style: 'width:80%;height:80%;margin-top:5px;', alt: '保存的图片', src: dataURL }, 'VNode'),
                    ]),
                    '✅ 图片预览',
                    {
                        confirmButtonText: '下载',
                        cancelButtonText: '取消',
                        // type: 'success',
                        dangerouslyUseHTMLString: true,
                    }
                )
                    .then(async () => {
                        await this.saveCanvas()
                        ElMessage({
                            type: 'success',
                            message: '保存成功',
                        })
                    })
                    .catch(() => {
                        ElMessage({
                            type: 'info',
                            message: '已取消',
                        })
                    })

            } catch (error) {
                console.error("图片保存错误:", error);
            }
        },
        /** 重置 */
        resetAllTool() {
            if (!this.checkViewport()) return
            // 重置工具
            // const annotation = localStorage.getItem("annotation");
            // if (annotation) {
            //     const a = JSON.parse(annotation)
            //     a.data.cachedStats = [];
            //     console.log("重置工具", a);
            //     cornerstoneTools.annotation.state.addAnnotation(
            //         a,
            //         this.viewport.element
            //     );
            // }
            // cornerstoneTools.cancelActiveManipulations(this.$refs["cornerstone-element"]);
            // 刷新页面
            window.location.reload();
            // this.viewport.reset();
            // this.viewport.render();
        },
    },

};
</script>

<style scoped>
.color {
    filter: sepia() saturate(4) hue-rotate(250deg);
}
.text{
    font-size: 1.1vw;
}
.el-step.is-vertical .el-step__title{
    font-size: 1.5vw;
}

.showDicom {
    margin-top: 100px;
    padding: 0px 2vw;
    display: flex;
}

.showDicom_left {
    text-align: center;
    flex: 0.35;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
    background: #171717;
    margin-top: 30px;
    margin-bottom: 30px;
    border-radius: 15px;
    box-shadow: inset 2px 2px 10px rgba(0, 0, 0, 1),
        inset -1px -1px 5px rgba(255, 255, 255, 0.6);
}

.showDicom_middle {
    flex: 0.4;
    padding: 30px;
    margin: 30px;
    /* padding: 65px 45px; */
    background: #171717;
    border-radius: 15px;
    box-shadow: inset 2px 2px 10px rgba(0, 0, 0, 1),
        inset -1px -1px 5px rgba(255, 255, 255, 0.6);
}

.showDicom_right {
    flex: 0.25;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
    background: #171717;
    padding: 30px;
    margin-top: 30px;
    margin-bottom: 30px;
    border-radius: 15px;
    box-shadow: inset 2px 2px   10px rgba(0, 0, 0, 1),
        inset -1px -1px 5px rgba(255, 255, 255, 0.6);
}
.showDicom_right_title{
    width: 100%;
    font-size: 1.6vw;
    font-weight: bold;
    text-align: center;
}
.card-header{
    width: 100%;
    font-size: 1.6vw;
    font-weight: bold;
    text-align: center;
    margin: 30px 0;
}

/* 信息表 */
.showDicom_title {
    width: 100%;
}

.showDicom_msg {
    padding: 10px;
    width: 86%;
    height: 36%;
    overflow-y: auto;
    /* border: 2px dashed rgba(220, 220, 220, 0.5); */
    /* border-radius: 6px; */

    background-color: #212121;
    border-radius: 6px;
    border: 2px solid #212121;
    box-shadow: 6px 6px 10px rgb(0 0 0), 1px 1px 10px rgb(255 255 255 / 60%);
    color: #ffffff;
}

.showDicom_steps {
    padding: 10px 20px;
    width: 86%;
    height: 36%;
    overflow-y: auto;

    /* border: 2px dashed rgba(220, 220, 220, 0.5);
    border-radius: 6px; */

    background-color: #212121;
    border-radius: 6px;
    border: 2px solid #212121;
    box-shadow: 6px 6px 10px rgb(0 0 0), 1px 1px 10px rgb(255 255 255 / 60%);
    color: #ffffff;
    margin-bottom: 10px;
}

/** 按钮 */
.showDicom_btn {
    width: 85%;
    margin: 20px 0;
    padding: 10px 35px;
    cursor: pointer;
    background-color: #212121;
    border-radius: 6px;
    border: 2px solid #212121;
    box-shadow: 6px 6px 10px rgba(0, 0, 0, 1),
        1px 1px 10px rgba(255, 255, 255, 0.6);
    color: #ffffff;
    font-size: 1.3vw;
    font-weight: bold;
    transition: 0.35s;
}

/* 颜色文字 */
.demonstration{
    font-size: 1.3vw;
}

.showDicom_btn_active {
    box-shadow: 6px 6px 10px rgba(0, 0, 0, 1),
        1px 1px 10px #00FF7F;
}

.showDicom_btn:active {
    transition: 100ms;
    transform: scale(1.05);
    box-shadow: 6px 6px 10px rgba(0, 0, 0, 1),
        1px 1px 10px rgba(255, 255, 255, 0.6),
        inset 2px 2px 10px rgba(0, 0, 0, 1),
        inset -1px -1px 5px rgba(255, 255, 255, 0.6);
}

/* 提示 */
.cornerstone_title {
    text-align: center;
    color: #808080;
    font-size: 7px;
    font-weight: bold;
    position: absolute;
    bottom: -23px;
    width: 100%;
}

/* 基石 */
.cornerstone_content {
    display: flex;
    position: relative;
}

.cornerstone_element {
    margin: 0 auto;
    max-width: 660px;
    max-height: 660px;
    width: 50vw;
    height: 50vw;
}

.cornerstone_shade {
    position: absolute;
    z-index: 100;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: black;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid gray;
    border-radius: 5px;
    padding: 100px;
}

.cornerstone_dragger {
    /* display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap; */
    width: 100%;
    height: 100%;
    border: 1px dashed gray;
    border-radius: 6px;
    box-sizing: border-box;
    text-align: center;
    cursor: pointer;
    background-color: #161616;

}

.cornerstone_dragger_input {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
}

.cornerstone_dragger:hover {
    box-shadow: 0px 15px 60px #00FF7F;
    outline: 1px solid #2b9962;
    border-radius: 10px;
}

.cornerstone_dragger_img {
    display: block;
    margin: 0 auto;
    margin-top: 20%;
    width: 15%;
}


.showDicom_middle_upload {
    display: block;
    width: 100%;
    /* height: 75vh; */
    /* background-color: aqua; */
}
</style>